package main

import (
	"bytes"
	"fmt"
	"image"
	"log"
	"os"
	"runtime"
	"strings"
	"syscall"

	"net"
	"net/http"
	"path/filepath"

	"github.com/lxn/walk"
	. "github.com/lxn/walk/declarative"
	"github.com/skip2/go-qrcode"
	"golang.org/x/sys/windows/registry"
)

const menuName = "二维码分享"

const port = 6686

func init() {
	// 确保在主线程中运行GUI
	runtime.LockOSThread()
}

func main() {
	fmt.Println("调用二维码分享服务")
	for i := range os.Args {
		fmt.Println(os.Args[i])
	}
	args := os.Args
	// args = []string{"", "share", `F:\Wingene\Location\Temp\apk\export\dgp02\release\dgp02-1_2.0.1.apk`}
	if len(args) > 1 && args[1] == "share" {
		// hideConsoleWindow()
		// url := "这是一个测试"
		filePath := args[2]
		fmt.Println("尝试启动服务")
		url, ln, err := startServer(filePath)
		if err != nil {
			log.Fatal("启动网络服务失败：", err)
		}
		fmt.Println("下载链接：", url)
		go func() {
			defer ln.Close()
			http.Serve(ln, nil)
		}()
		share(url)
		// fmt.Println("请按下任意键退出...")
		// fmt.Scanln()
	} else {
		Registry()
		// share("dd")
		// ip, err := GetLocalIP()
		// fmt.Println("ip is" + ip)
		// if err != nil {
		// 	fmt.Println(err)
		// }
	}
}

func Registry() {
	// 检查右键菜单是否已存在
	key, _, err := registry.CreateKey(registry.CLASSES_ROOT, `*\shell\`+menuName, registry.QUERY_VALUE)
	if err != nil {
		fmt.Println("创建注册表键失败：", err)
		return
	}
	defer key.Close()

	_, _, err = key.GetStringValue("Icon")
	if err != nil && err != registry.ErrNotExist {
		fmt.Println("获取Icon属性失败：", err)
		return
	}

	cmdKey, _, err := registry.CreateKey(key, "command", registry.SET_VALUE)
	if err != nil {
		fmt.Println("创建command子键失败：", err)
		return
	}
	defer cmdKey.Close()

	exePath, err := os.Executable()
	if err != nil {
		fmt.Println("获取可执行文件路径失败：", err)
		return
	}

	err = cmdKey.SetStringValue("", fmt.Sprintf(`"%s" share "%%1"`, exePath))
	if err != nil {
		fmt.Println("设置command属性失败：", err)
		return
	}

	fmt.Println("在右键菜单中，增加了'二维码分享'按钮")
	fmt.Println()
	fmt.Println("请按下任意键退出...")
	fmt.Scanln()
}

func hideConsoleWindow() {
	kernel32 := syscall.NewLazyDLL("kernel32.dll")
	proc := kernel32.NewProc("FreeConsole")
	proc.Call()
}

func startServer(filePath string) (string, net.Listener, error) {
	// 获取文件名和文件大小
	fileName := filepath.Base(filePath)
	fileInfo, err := os.Stat(filePath)
	if err != nil {
		return "", nil, err
	}
	fileSize := fileInfo.Size()

	// 启动 HTTP 服务
	ln, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
	if err != nil {
		return "", nil, err
	}
	ip, err := GetLocalIP()
	if err != nil {
		return "", nil, err
	}
	// 提供文件下载链接
	fileUrl := fmt.Sprintf("http://%s:%v/%s", ip, port, fileName)
	fmt.Println("下载地址:", fileUrl)
	http.HandleFunc(fmt.Sprintf("/%s", fileName), func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s", fileName))
		w.Header().Set("Content-Type", "application/octet-stream")
		w.Header().Set("Content-Length", fmt.Sprintf("%d", fileSize))
		http.ServeFile(w, r, filePath)
	})
	// go http.Serve(ln, nil)
	return fileUrl, ln, nil
}

func stopServer() {
	http.DefaultServeMux = http.NewServeMux()
}

func GetLocalIP() (string, error) {
	addrs, err := net.InterfaceAddrs()
	if err != nil {
		return "", fmt.Errorf("无法获取本机IP：%v", err)
	}

	for _, addr := range addrs {
		if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
			if ipnet.IP.To4() != nil {
				ip := ipnet.IP.String()
				if strings.HasPrefix(ip, "192.168") && !strings.HasSuffix(ip, ".1") {
					return ip, nil
				}
			}
		}
	}

	return "", fmt.Errorf("无法取到有效的IP")
}

func share(url string) {
	if _, err := (MainWindow{
		Title:   "分享二维码",
		Layout:  VBox{MarginsZero: true, SpacingZero: true},
		Size:    Size{300, 300},
		MinSize: Size{280, 280},
		MaxSize: Size{320, 320},
		Children: []Widget{
			ImageView{
				Image:  qrcodeImage(url),
				Margin: 10,
			},
		},
	}.Run()); err != nil {
		fmt.Printf("创建窗口失败: %v\n", err)
		return
	}
}

func qrcodeImage(data string) *walk.Bitmap {
	qrcodeImg, err := qrcode.Encode(data, qrcode.Medium, 256)
	if err != nil {
		fmt.Println("生成二维码失败: ", err)
		return nil
	}
	// 将二进制图像数据解码为图像对象
	img, _, err := image.Decode(bytes.NewReader(qrcodeImg))
	if err != nil {
		fmt.Println("解码二维码图像失败: ", err)
		return nil
	}
	// 将图像对象转换为Bitmap对象
	bmp, err := walk.NewBitmapFromImage(img)
	if err != nil {
		fmt.Println("创建Bitmap对象失败: ", err)
		return nil
	}
	return bmp
}
